package utilities;

import eccezioni.FacebookNotLinkedException;
import entity.Adesione;
import entity.Annuncio;
import entity.UtenteRegistrato;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import statefulSB.UtenteLoggatoLocal;
import utilities.json.JSONArray;
import utilities.json.JSONException;
import utilities.json.JSONObject;
import utilities.json.JSONReader;

/**
 *
 * @author fabio
 */
public class FbUtilities {

    /**
     * Metodo che stabilisce se l'utente correntemente loggato è amico di un
     * altro utente registrato nel sistema
     * @param user l'utente correntemente loggato
     * @param friend l'utente cn cui si vuoel verificare l'amicizia
     * @return true se gli utenti sono amici, false altrimenti
     * @throws FacebookNotLinkedException se l'utente loggato non ha eseguito il
     * collegamento tra Shipping Share e il proprio account Facebook
     */
    public static boolean isFriendOf(UtenteLoggatoLocal user, UtenteRegistrato friend) throws FacebookNotLinkedException {
        try {
            if (user.getFacebookToken() == null) {
                throw new FacebookNotLinkedException();
            }
            String url = "https://graph.facebook.com/me/friends?access_token=" + user.getFacebookToken();
            JSONObject reply;
            String id = friend.getFacebookId();
            reply = JSONReader.readJSONFromUrl(url);
            JSONArray a = reply.getJSONArray("data");
            for (int i = 0; i < a.length(); i++) {
                if (a.getJSONObject(i).getString("id").equals(id)) {
                    return true;
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(FbUtilities.class.getName()).log(Level.SEVERE, null, ex);
        } catch (JSONException ex) {
            Logger.getLogger(FbUtilities.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }


    /**
     * Metodo per estrarre da una lista di annunci gli annunci pubblicati da un 
     * amico di Facebook dell'utente loggato.
     * @param user utente correntemente loggato
     * @param annunci lista di annunci da filtrare
     * @return gli annunci pubblicati da un amico di Facebook dell'utente loggato
     * @throws FacebookNotLinkedException se l'utente loggato non ha eseguito il
     * collegamento tra Shipping Share e il proprio account Facebook 
     */
    public static List<AnnuncioConDistanza> isFriendOf(UtenteLoggatoLocal user, List<AnnuncioConDistanza> annunci) throws FacebookNotLinkedException {

        List<AnnuncioConDistanza> l = new LinkedList<AnnuncioConDistanza>();
        if (user.getFacebookToken() == null) {
            throw new FacebookNotLinkedException();
        }
        try {
            String url = "https://graph.facebook.com/me/friends?access_token=" + user.getFacebookToken();
            JSONObject reply;
            reply = JSONReader.readJSONFromUrl(url);
            JSONArray a = reply.getJSONArray("data");
            String[] friends = new String[a.length()];
            for (int i = 0; i < a.length(); i++) {//O(n)
                friends[i] = a.getJSONObject(i).getString("id");

            }
            Arrays.sort(friends);//O(nlogn)
            for (AnnuncioConDistanza ann : annunci) {//O(nlogn)
                if (Arrays.binarySearch(friends, ann.getAnnuncio().getCreatoreAnnuncio().getFacebookId()) >= 0) {
                    l.add(ann);
                }
            }

            return l;
        } catch (IOException ex) {
            Logger.getLogger(FbUtilities.class.getName()).log(Level.SEVERE, null, ex);
        } catch (JSONException ex) {
            Logger.getLogger(FbUtilities.class.getName()).log(Level.SEVERE, null, ex);
        }
        return l;
    }

    /**
     * Metodo per estrarre da un annuncio la lista di adesioni di utenti amici
     * di Facebook dell'utente correntemente loggato.
     * @param user utente correntemente loggato
     * @param annuncio annuncio di cui filtrare le adesioni
     * @return lista di adesioni all'annuncio di un amico di Facebook dell'utente loggato
     * @throws FacebookNotLinkedException se l'utente loggato non ha eseguito il
     * collegamento tra Shipping Share e il proprio account Facebook 
     */
    public static List<Adesione> isFriendOf(UtenteLoggatoLocal user, Annuncio annuncio) throws FacebookNotLinkedException {
        List<Adesione> list = new LinkedList<Adesione>();
        if (user.getFacebookToken() == null) {
            throw new FacebookNotLinkedException();
        }
        try {

            String url = "https://graph.facebook.com/me/friends?access_token=" + user.getFacebookToken();
            JSONObject reply;
            reply = JSONReader.readJSONFromUrl(url);
            JSONArray a = reply.getJSONArray("data");
            String[] friends = new String[a.length()];
            for (int i = 0; i < a.length(); i++) {//O(n)
                friends[i] = a.getJSONObject(i).getString("id");

            }
            Arrays.sort(friends);//O(nlogn)
            for (Adesione ad : annuncio.getAdesioni()) {//O(nlogn
                if (Arrays.binarySearch(friends, ad.getIscritto().getFacebookId()) >= 0) {
                    list.add(ad);
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(FbUtilities.class.getName()).log(Level.SEVERE, null, ex);
        } catch (JSONException ex) {
            Logger.getLogger(FbUtilities.class.getName()).log(Level.SEVERE, null, ex);
        }
        return list;
    }
}
